package com.xhwl.logistics.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhwl.common.enums.OrganizationTypeEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.sdata.Account;
import com.xhwl.common.pojo.cent.sdata.Organization;
import com.xhwl.common.pojo.cent.sdata.Project;
import com.xhwl.common.pojo.cent.vehicle.VehcArea;
import com.xhwl.common.pojo.cent.vehicle.VehcCarSpot;
import com.xhwl.common.pojo.cent.vehicle.VehcParkingLot;
import com.xhwl.common.pojo.cent.vehicle.VehcPassage;
import com.xhwl.common.query.cent.sdata.AccountQuery;
import com.xhwl.common.query.cent.sdata.ProjectQuery;
import com.xhwl.common.query.cent.vehicle.ParkingLotQuery;
import com.xhwl.common.utils.ChkUtil;
import com.xhwl.common.vo.cent.vehicle.ParkingLotVO;
import com.xhwl.common.vo.cent.vehicle.VehicleCardCarStatisticsVO;
import com.xhwl.logistics.bo.cent.VehicleIntegratedConfigBO;
import com.xhwl.logistics.dao.VehcAreaDao;
import com.xhwl.logistics.dao.VehcCarSpotDao;
import com.xhwl.logistics.dao.VehcParkingLotDao;
import com.xhwl.logistics.dao.VehcPassageDao;
import com.xhwl.logistics.entity.VehicleCar;
import com.xhwl.logistics.enums.VehicleCardTypeEnum;
import com.xhwl.logistics.enums.VehicleCodeEnum;
import com.xhwl.logistics.service.IVehcAreaService;
import com.xhwl.logistics.service.IVehcParkingLotService;
import com.xhwl.logistics.service.cent.IAccountService;
import com.xhwl.logistics.service.cent.IOrganizationService;
import com.xhwl.logistics.service.cent.IProjectService;
import com.xhwl.logistics.service.cent.QueryDeviceService;
import com.xhwl.logistics.util.EscapeCharacter;
import com.xhwl.logistics.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Lu.Aaron
 * @since 2021-02-08
 */
//@Service
public class VehcParkingLotServiceImpl extends ServiceImpl<VehcParkingLotDao, VehcParkingLot> implements IVehcParkingLotService {
    @Autowired
    private VehcParkingLotDao vehcParkingLotDao;
    @Autowired
    private IVehcAreaService iVehcAreaService;
    @Autowired
    private VehcAreaDao vehcAreaDao;
    @Autowired
    private VehcCarSpotDao vehcCarSpotDao;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private IProjectService projectService;
    @Autowired
    private VehcPassageDao vehcPassageDao;
    @Autowired
    private IOrganizationService organizationService;
    @Autowired
    private QueryDeviceService queryDeviceService;
    @Autowired
    private VehicleCarServiceImpl vehicleCarService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(ParkingLotVO parkingLotVO, Account account, Short industryId) {
        //TODO 根据String syncManufacturer = parkingLotVO.getSyncManufacturer()判断选择供应商，同步数据;
        //TODO 若syncManufacturer空，通过项目查询供应商，在进行同步数据

        Integer name = vehcParkingLotDao.selectCount(new QueryWrapper<VehcParkingLot>().eq("name", parkingLotVO.getName()).eq("project_id",parkingLotVO.getProjectId()));
        if (name>=1) {
            throw new BusinessException(VehicleCodeEnum.NAME_DUPLICATE.description);
        }
        if (Objects.isNull(parkingLotVO.getProjectOrgId())) {
            throw new BusinessException("缺少必要参数：projectOrgId");
        }
        if (null==parkingLotVO.getEnterpriseId()) {
            throw new BusinessException("缺少必要参数：enterpriseId");
        }
        if (null==parkingLotVO.getLevel()) {
            throw new BusinessException("缺少必要项目层级数参数：level");
        }
        //TODO 1.调用主数据服务，与sdata_organization表建立关联
        Organization organization = new Organization();
        organization.setParentId(parkingLotVO.getProjectOrgId());
        organization.setEnterpriseId(parkingLotVO.getEnterpriseId());
        organization.setName(parkingLotVO.getName());
        organization.setLevel(parkingLotVO.getLevel()+1);
        organization.setIndustryId(industryId);

        //cent-common修改Organization setType
        organization.setType(OrganizationTypeEnum.PARKING_LOT.getId().intValue());

        Account accountQuery = new Account();
        ResultJson<Integer> resultJson = organizationService.create(organization, accountQuery);
        Integer orgId = resultJson.getResult();
        //TODO  2.新增车场信息
        VehcParkingLot vehcParkingLot = new VehcParkingLot();
        BeanUtils.copyProperties(parkingLotVO,vehcParkingLot);
        vehcParkingLot.setCreatorAccountId(account.getId());
        vehcParkingLot.setOrgId(orgId);
        vehcParkingLotDao.insert(vehcParkingLot);
        areaSaveBatch(parkingLotVO, vehcParkingLot.getId(),orgId, industryId);
        //TODO 3.若需要同步则同步，根据接口厂商能力 true代表需要同步，false代表不需要同步


    }

    private void areaSaveBatch(ParkingLotVO parkingLotVO, Integer id, Integer parentOrgId, Short industryId) {

        List<String> areaName = parkingLotVO.getAreaName();
        if (areaName.isEmpty()) {
            return;
        }
        List<Organization> organizations = new ArrayList<>();

        areaName.forEach(a->{
            Organization organization = new Organization();
            organization.setEnterpriseId(parkingLotVO.getEnterpriseId());
            organization.setIndustryId(industryId);
            organization.setParentId(parentOrgId);
            organization.setLevel(parkingLotVO.getLevel()+2);

            //cent-common修改Organization setType
            organization.setType(OrganizationTypeEnum.PARKING_AREA.getId().intValue());

            organization.setName(a);
            organizations.add(organization);
        });
        //TODO 1.调用主数据服务，与sdata_organization表建立关联
        ResultJson resultJson = organizationService.create(organizations, new Account());
        Object result = resultJson.getResult();
        List<Organization> list = JSON.parseArray(JSON.toJSONString(result), Organization.class);
        //TODO 2.新增区域
        List<VehcArea> vehcAreas =new ArrayList<>();

        list.forEach(o->{
            VehcArea vehcArea = new VehcArea();
            vehcArea.setName(o.getName());
            vehcArea.setParkingLotId(id);
            vehcArea.setOrgId(o.getId());
            vehcAreas.add(vehcArea);
        });
        iVehcAreaService.saveBatch(vehcAreas);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(ParkingLotVO parkingLotVO, Account account, Short industryId) {
        //TODO 根据String syncManufacturer = parkingLotVO.getSyncManufacturer()判断选择供应商，同步数据;
        //TODO 若syncManufacturer空，通过项目查询供应商，在进行同步数据
        Integer name = vehcParkingLotDao.selectCount(new QueryWrapper<VehcParkingLot>().eq("name", parkingLotVO.getName()).eq("project_id",parkingLotVO.getProjectId()));
        if (name>=1) {
            throw new BusinessException(VehicleCodeEnum.NAME_DUPLICATE.description);
        }
        Integer id = parkingLotVO.getId();
        if (null==id) {
            throw new BusinessException(VehicleCodeEnum.ID_NO_EXIST.description);
        }
        if (Objects.isNull(parkingLotVO.getOrgId())) {
            throw new BusinessException("缺少必要参数：orgId");
        }
        if (Objects.isNull(parkingLotVO.getProjectOrgId())) {
            throw new BusinessException("缺少必要参数：projectOrgId");
        }
        if (null==parkingLotVO.getEnterpriseId()) {
            throw new BusinessException("缺少必要参数：enterpriseId");
        }
        if (null==parkingLotVO.getLevel()) {
            throw new BusinessException("缺少必要项目层级数参数：level");
        }
        //TODO 1.调用主数据服务，在sdata_organization表进行修改车场
        Organization parkingLotOrganization = new Organization();
        VehcParkingLot vehcParkingLotQuery = vehcParkingLotDao.selectById(id);
        parkingLotOrganization.setParentId(parkingLotVO.getProjectOrgId());
        parkingLotOrganization.setName(parkingLotVO.getName());
        parkingLotOrganization.setId(vehcParkingLotQuery.getOrgId());

        parkingLotOrganization.setEnterpriseId(parkingLotVO.getEnterpriseId());
        parkingLotOrganization.setLevel(parkingLotVO.getLevel()+1);
        parkingLotOrganization.setIndustryId(industryId);

        //cent-common修改Organization setType
        parkingLotOrganization.setType(OrganizationTypeEnum.PARKING_LOT.getId().intValue());

        organizationService.update(parkingLotOrganization, null);
        //TODO 2.同步修改车场
        VehcParkingLot vehcParkingLot = new VehcParkingLot();
        BeanUtils.copyProperties(parkingLotVO,vehcParkingLot);
        vehcParkingLotDao.updateById(vehcParkingLot);
        //TODO 3.调用主数据服务，先删除原来区域再新增
        List<VehcArea> vehcAreas = vehcAreaDao.selectList(new QueryWrapper<VehcArea>().eq("parking_lot_id", id));
        List<Integer> areaOrgIds = vehcAreas.stream().map(area -> area.getOrgId()).collect(Collectors.toList());
        organizationService.batchDelete(areaOrgIds);
        vehcAreaDao.delete(new QueryWrapper<VehcArea>().eq("parking_lot_id",id));
        areaSaveBatch(parkingLotVO, id, parkingLotVO.getOrgId(), industryId);
    }

    @Override
    public void delete(Integer id, Short industryId) {

        //TODO 通过id查询对应的projectId再查询对应的供应商
        //TODO 1.调用主数据服务，在sdata_organization表进行删除车场,同步删除车场下里面的区域，通道
        List<Integer> list = new ArrayList<>();
        VehcParkingLot vehcParkingLot = vehcParkingLotDao.selectById(id);
        list.add(vehcParkingLot.getOrgId());
        List<VehcArea> vehcAreas = vehcAreaDao.selectList(new QueryWrapper<VehcArea>().eq("parking_lot_id", vehcParkingLot.getId()));
        if (null!=vehcAreas&&!vehcAreas.isEmpty()) {
            vehcAreas.forEach(vehcArea -> list.add(vehcArea.getOrgId()));
            List<Integer> areaIds = vehcAreas.stream().map(vehcArea -> vehcArea.getId()).collect(Collectors.toList());
            List<VehcPassage> vehcPassages = vehcPassageDao.selectList(new QueryWrapper<VehcPassage>().in("area_id", areaIds));
            if (null!=vehcPassages&&!vehcPassages.isEmpty()) {
                vehcPassages.forEach(vehcPassage -> list.add(vehcPassage.getOrgId()));
            }
            List<VehcCarSpot> vehcCarSpots = vehcCarSpotDao.selectList(new QueryWrapper<VehcCarSpot>().in("area_id", areaIds));
            if (null!=vehcCarSpots&&!vehcCarSpots.isEmpty()) {
                vehcCarSpots.forEach(vehcCarSpot -> list.add(vehcCarSpot.getOrgId()));
            }
        }

        organizationService.batchDelete(list);
        //TODO 2.删除车场，同步删除车场下面相应的车位，通道,区域
        vehcParkingLotDao.deleteById(id);
        vehcAreaDao.delete(new QueryWrapper<VehcArea>().eq("parking_lot_id",id));
        vehcPassageDao.delete(new QueryWrapper<VehcPassage>().eq("parking_lot_id",id));
        vehcCarSpotDao.delete(new QueryWrapper<VehcCarSpot>().eq("parking_lot_id",id));
    }

    @Override
    public Page<VehcParkingLot> parkingLotPage(ParkingLotQuery parkingLotQuery) {
        /**
         * 对模糊查询字段停车场名称字段进行判断操作，防止sql注入
         */
        parkingLotQuery.setName(EscapeCharacter.escape(parkingLotQuery.getName()));
        String name = parkingLotQuery.getName();
        List<Integer> projectIds = parkingLotQuery.getProjectIds();
        Integer projectId = parkingLotQuery.getProjectId();
        if (null==projectIds&&null==projectId) {
            throw new BusinessException(VehicleCodeEnum.PROJECT_ID_LACK.description);
        }
        if (null!=projectIds&&projectIds.isEmpty()&&null==projectId) {
            throw new BusinessException(VehicleCodeEnum.PROJECT_ID_LACK.description);
        }
        Page<VehcParkingLot> page = new Page<>();
        page.setSize(parkingLotQuery.getPageSize());
        page.setCurrent(parkingLotQuery.getCurrent());
        QueryWrapper<VehcParkingLot> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        if (StringUtils.isNotBlank(name)) {
            wrapper.like("name",name);
        }
        if (null!=projectIds&&!projectIds.isEmpty()) {
            wrapper.in("project_id",projectIds);
        }
        if (null!=projectId) {
            wrapper.eq("project_id",projectId);
        }
        Page<VehcParkingLot> vehcParkingLotPage = vehcParkingLotDao.selectPage(page, wrapper);
        List<VehcParkingLot> vehcParkingLots = vehcParkingLotPage.getRecords();
        if (!vehcParkingLots.isEmpty()) {
            // 统计该项目中各卡片类型对应的车的数量（月卡车、产权车等）
            List<VehicleCardCarStatisticsVO> vehicleCardCarStatisticsVOList = cardCarStatistics(projectId);
            // 单项目对应的单车场，不考虑多车场的情况
            vehcParkingLots.get(0).setVehicleCardCarStatisticsVOList(vehicleCardCarStatisticsVOList);

            List<Integer> parkingLotIds = vehcParkingLots.stream().map(v -> v.getId()).collect(Collectors.toList());
            //设置所属区域
            List<VehcArea> vehcAreas = vehcAreaDao.selectList(new QueryWrapper<VehcArea>().in("parking_lot_id", parkingLotIds));
            if (!vehcAreas.isEmpty()) {
                vehcParkingLots.forEach(v->{
                    StringBuilder stringBuilder = new StringBuilder();
                    for (VehcArea vehcArea : vehcAreas) {
                        if (vehcArea.getParkingLotId().equals(v.getId())) {
                            stringBuilder.append(vehcArea.getName()).append("、");
                        }
                    }

                    if (stringBuilder.length()>0) {
                        String areaListStr = stringBuilder.substring(0, stringBuilder.length() - 1);
                         v.setAreaList(areaListStr);
                    }
                    if (stringBuilder.length()==0) {
                        v.setAreaList("无");
                    }
                });
            }
            if (vehcAreas.isEmpty()) {
                vehcParkingLots.forEach(v->v.setAreaList("无"));
            }
            //设置车位数

            List<VehcCarSpot> vehcCarSpots = vehcCarSpotDao.selectList(new QueryWrapper<VehcCarSpot>().in("parking_lot_id", parkingLotIds));
            if (!vehcCarSpots.isEmpty()) {
                vehcParkingLots.forEach(v->{
                        int num=0;
                        for (VehcCarSpot vehcCarSpot : vehcCarSpots) {
                            if (vehcCarSpot.getParkingLotId().equals(v.getId())) {
                                num++;
                            }
                        }
                        v.setCarSpotNum(num);
                });
            }

            //根据creator_account_id查找创建人名字
            List<Integer> accountIds = vehcParkingLots.stream().map(v -> v.getCreatorAccountId()).collect(Collectors.toList());
            AccountQuery accountQuery = new AccountQuery();
            accountQuery.setIdList(accountIds);
            List<Account> accounts = accountService.getAccountList(null, accountQuery);
            vehcParkingLots.forEach(vp->{
                if (Objects.nonNull(vp.getCreatorAccountId())) {
                    accounts.forEach(a->{
                        if (vp.getCreatorAccountId().equals(a.getId())) {
                            vp.setCreatorAccountName(a.getName());
                        }
                    });
                }
            });
            //根据projectId查询
            List<Integer> projectIdList = vehcParkingLots.stream().map(v -> v.getProjectId()).collect(Collectors.toList());
            ProjectQuery projectQuery = new ProjectQuery();
            projectQuery.withIdList(projectIdList);
            List<Project> projects = projectService.list(projectQuery, null);
            vehcParkingLots.forEach(vp->{
                projects.forEach(p->{
                    if (vp.getProjectId().equals(p.getId())) {
                        vp.setProjectName(p.getName());
                    }
                });
            });
        }

        return vehcParkingLotPage;
    }

    @Override
    public List<VehcParkingLot> list(ParkingLotQuery parkingLotQuery) {
        QueryWrapper<VehcParkingLot> wrapper = new QueryWrapper<>();
        if (Objects.nonNull(parkingLotQuery.getProjectId())) {
            wrapper.eq("project_id",parkingLotQuery.getProjectId());
        }
        if (Objects.nonNull(parkingLotQuery.getProjectIds())&&!parkingLotQuery.getProjectIds().isEmpty()) {
            wrapper.in("project_id", parkingLotQuery.getProjectIds());
        }
        if (Objects.nonNull(parkingLotQuery.getName())) {
            wrapper.like("name", parkingLotQuery.getName());
        }
        return vehcParkingLotDao.selectList(wrapper);
    }

    /**
     * 通过项目id获取第三方的车场id
     */
    @Override
    public ResultJson getParkIdByProjectId(Integer projectId) {
        if(projectId == null){
            throw new BusinessException("项目id为空！");
        }
        List<VehcParkingLot> vehcParkingLots = vehcParkingLotDao.selectList(conditionForParkingByProjectId(projectId));
        if(vehcParkingLots.size()>1){
            throw new BusinessException("该项目下有多个车场！");
        }else if(vehcParkingLots.size()<1){
            throw new BusinessException("该项目下没有车场！");
        }else {
            VehicleIntegratedConfigBO vehicleIntegratedConfigBO = queryDeviceService.queryIntegratedConfigFromProjectId(projectId);
            if(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId() != null){
                if(!org.apache.commons.lang3.StringUtils.equals(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId(),
                        vehcParkingLots.get(0).getThirdParkId())){
                    throw new BusinessException("当前第三方车场id不是最新的，请先同步车场id");
                }
            }
            return ResultJson.successWithResult(vehcParkingLots.get(0).getThirdParkId());
        }
    }

    /**
     * 通过项目id查询第三方车场id的条件
     */
    private Wrapper<VehcParkingLot> conditionForParkingByProjectId(Integer projectId){
        return new LambdaQueryWrapper<VehcParkingLot>()
                .eq(VehcParkingLot::getProjectId, projectId);
    }


    public List<VehicleCardCarStatisticsVO> cardCarStatistics(Integer projectId) {
        LambdaQueryWrapper<VehicleCar> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(VehicleCar::getProjectId, projectId);
        List<VehicleCar> carList = vehicleCarService.list(lambdaQueryWrapper);
        if(ChkUtil.isNull(carList)) {
            return new ArrayList<>();
        }
        List<VehicleCardCarStatisticsVO> result = new ArrayList<>();
        Map<Integer, List<VehicleCar>> carMap = carList.stream().collect(Collectors.groupingBy(VehicleCar::getCardType));
        for(Integer type : carMap.keySet()) {
            VehicleCardTypeEnum vehicleCardTypeEnum = VehicleCardTypeEnum.toVehicleCardTypeEnum(type);
            VehicleCardCarStatisticsVO vo = new VehicleCardCarStatisticsVO();
            vo.setCardTypeId(vehicleCardTypeEnum.getId());
            vo.setCardTypeCode(vehicleCardTypeEnum.getCode());
            vo.setDescription(vehicleCardTypeEnum.getDescription());
            vo.setNum(carMap.get(type).size());
            result.add(vo);
        }
        return result;
    }
}
